import { IController, IControllerParams, IParam, IStore } from '@/core';
import { IAbility } from '@/core/interface/modules/common/i-ability';

/**
 * 控制器基类
 *
 * @export
 * @class ControllerBase
 * @implements {IController<T>}
 * @template T
 */
export class ControllerBase<S extends IStore, A extends IAbility>
	implements IController<S, A>
{
	/**
	 * 控制器名称
	 *
	 * @protected
	 * @type {string}
	 * @memberof ControllerBase
	 */
	protected name!: string;

	/**
	 * 视图模型数据
	 *
	 * @protected
	 * @type {IParam}
	 * @memberof ControllerBase
	 */
	protected readonly model: IParam = {};

	/**
	 * 回调处理函数
	 *
	 * @protected
	 * @type {Function}
	 * @memberof ControllerBase
	 */
	protected readonly handler?: Function;

	/**
	 * 控制器仓库数据
	 *
	 * @protected
	 * @type {T}
	 * @memberof ControllerBase
	 */
	protected store!: S;

	/**
	 * 子能力中枢
	 *
	 * @protected
	 * @type {Map<string, IWidgetNeuron>}
	 * @memberof ControllerBase
	 */
	protected subAbilityCenter: Map<string, IAbility> = new Map();

	/**
	 * Creates an instance of ControllerBase.
	 * @param {IControllerParams} params
	 * @memberof ControllerBase
	 */
	constructor(params: IControllerParams) {
		this.model = params.model;
		this.handler = params.handler;
		this.name = params.name ? params.name : this.model.name;
	}

	/**
	 * 初始化仓库数据
	 *
	 * @memberof ControllerBase
	 */
	initStore() {
		if (this.handler) {
			this.store = this.handler(this.store);
		}
	}

	/**
	 * 获取能力
	 *
	 * @template A
	 * @return {*}  {A}
	 * @memberof ControllerBase
	 */
	getAbility(): A {
		return {
			name: this.name,
			getModel: this.getModel.bind(this),
		} as A;
	}

	/**
	 * 设置子能力块
	 *
	 * @param {string} name
	 * @param {IAbility} subAbility
	 * @memberof ControllerBase
	 */
	setSubAbility(name: string, subAbility: IAbility) {
		this.subAbilityCenter.set(name, subAbility);
	}

	/**
	 * 获取子能力块
	 *
	 * @template A
	 * @param {string} name
	 * @return {*}  {TA}
	 * @memberof ControllerBase
	 */
	getSubAbility<A extends IAbility = IAbility>(name: string): A {
		return this.subAbilityCenter.get(name) as A;
	}

	/**
	 * 获取模型
	 *
	 * @template T
	 * @return {*}  {T}
	 * @memberof ControllerBase
	 */
	getModel<T>(): T {
		return this.model as T;
	}

	/**
	 * 获取仓库数据
	 *
	 * @return {*}  {T}
	 * @memberof ControllerBase
	 */
	getStore(): S {
		return this.store;
	}

	/**
	 * 获取数据
	 *
	 * @return {*}  {(IParam | IParam[])}
	 * @memberof ControllerBase
	 */
	getData(): IParam[] {
		const data: IParam | Array<IParam> = (this.store as IParam).data || {};
		const exposeData: Array<IParam> = [];
		this.computeExposeData(data, exposeData);
		return exposeData;
	}

	/**
	 * 计算暴露数据
	 */
	protected computeExposeData(
		data: IParam | Array<IParam>,
		targetData: Array<IParam>
	) {
		if (Array.isArray(data)) {
			data.forEach((item: IParam) => {
				this.computeExposeData(item, targetData);
			});
		} else {
			const itemData: IParam = {};
			if (data.$ownKeys) {
				data.$ownKeys.forEach((field: string) => {
					Object.assign(itemData, { [field]: data[field] });
				});
				itemData.$DO = data.$DO;
			} else {
				Object.assign(itemData, data);
			}
			targetData.push(itemData);
		}
		return targetData;
	}

	/**
	 * 设置导航参数
	 *
	 * @param {IParam} context 视图上下文
	 * @param {IParam} viewParams 视图导航参数
	 * @param {IParam} viewCtx 视图操作参数
	 * @memberof ControllerBase
	 */
	setNavParams(context: IParam, viewParams: IParam, viewCtx?: IParam): void {
		this.store.context = context;
		this.store.viewParams = viewParams;
		if (viewCtx) {
			if (viewCtx.appGlobal) {
				this.store.viewCtx.appGlobal = viewCtx.appGlobal;
			}
			if (viewCtx.routeViewGlobal) {
				this.store.viewCtx.routeViewGlobal = viewCtx.routeViewGlobal;
			}
		}
	}
	/**
	 * 初始化计数器数据
	 *
	 * @param {IParam} context
	 * @param {IParam} viewParams
	 * @memberof ControllerBase
	 */
	async initCounterData() {
		const cb = (tempCounterData: IParam) => {
			this.store.counterData = tempCounterData;
		};
		if (this.model?.counters?.length > 0) {
			for (let i = 0; i < this.model.counters.length; i++) {
				const tag = this.model.counters[i];
				this.store.counterData = {};
				await App.getAppCounterHelper().getCounterItems(
					tag,
					this.store.context,
					this.store.viewParams,
					cb
				);
			}
		}
	}

	/**
	 * 销毁计数器
	 *
	 * @memberof ControllerBase
	 */
	destroyCounter() {
		if (this.model?.counters?.length > 0) {
			for (let i = 0; i < this.model.counters.length; i++) {
				const tag = this.model.counters[i];
				App.getAppCounterHelper().destroyCounter(tag);
			}
		}
	}
}
